import inputs.Input;
import inputs.PixelInput;

import java.util.ArrayList;

import javax.sound.midi.Receiver;

import management.MidiManager;
import management.MidiManager.MidiVoices;
import midi.PitchVelocityMidiOutParameter;

import outputAdapters.OutputAdapter;
import outputAdapters.OutputRanges;

import processingHandling.WebCamPAppletWrapper;

import dataModifiers.Modifier;

public class Set_1 extends WebCamPAppletWrapper{
	
	// ----- Pixels! ------
	PixelInput upperLeftPixel, lowerLeftPixel, upperRightPixel, lowerRightPixel;
	PixelInput centerPixel;

	// ----- Modifiers! -----
	Modifier upperLeftPixelSumMod, lowerLeftPixelSumMod, upperRightPixelSumMod, lowerRightPixelSumMod;
	Modifier outerFourPixelsAverageMod, outerFourPixelsAverageHighPassMod;
	Modifier lowerLeftPixelRAverageMod, centerPixelGAverageMod, upperRightPixelBAverageMod;
	
	// ----- OutputAdapters! -----
	OutputAdapter lowerLeftPixelAverageScaleAdapter;
	OutputAdapter upperRightPixelAverageScaleAdapter;
	OutputAdapter outerFourPixelsAverageHighPassScaleAdapter;
	OutputAdapter centerPixelAverageScaleAdapter;
	
	// ----- MidiOutParams! -----
	PitchVelocityMidiOutParameter dronePitchVelOut; // Midi Out Parameter to drive the Drone's Pitch and Velocity;
	PitchVelocityMidiOutParameter arpPitchVelOut; // Midi Out Parameter to drive the Arpeggio's Pitch and Velocity;
	PitchVelocityMidiOutParameter harmPitchVelOut; // Midi Out Parameter to drive the Harmony's Pitch and Velocity;

	// ---- midiRec! -----
	Receiver midiYoke1Rec; // Midi Receiver used to write to MidiYoke1
	
	public void Setup() 
	{
		// pixel input position setup
		upperLeftPixel = TheInputFactory.createPixelInput(this.getWidth()/4, this.getHeight()/4, true);
		lowerLeftPixel = TheInputFactory.createPixelInput(this.getWidth()/4, this.getHeight()*3/4, true);
		upperRightPixel = TheInputFactory.createPixelInput(this.getWidth()*3/4, this.getHeight()/4, true);
		lowerRightPixel = TheInputFactory.createPixelInput(this.getWidth()*3/4, this.getHeight()*3/4, true);
		centerPixel = TheInputFactory.createPixelInput(this.getWidth()/2, this.getHeight()/2, true);

		
		
		  // lower left pixel R average setup
		  ArrayList<Input> lowerLeftRAverageInput = new ArrayList<Input>(1);
		  lowerLeftRAverageInput.add(lowerLeftPixel.getRedInput());
		  lowerLeftPixelRAverageMod = TheModifierFactory.createAverage(lowerLeftRAverageInput, true);
		  // set to be a running average
		  lowerLeftPixelRAverageMod.setRun(true);
		  
		  // upper right pixel B average setup
		  ArrayList<Input> upperRightBAverageInput = new ArrayList<Input>(1);
		  upperRightBAverageInput.add(upperRightPixel.getBlueInput());
		  upperRightPixelBAverageMod = TheModifierFactory.createAverage(upperRightBAverageInput, true);
		  // set to be a running average
		 // upperRightPixelBAverageMod.setRun(true);
		  
		  // center pixel G average setup
		  ArrayList<Input> centerGAverageInput = new ArrayList<Input>(1);
		  centerGAverageInput.add(centerPixel.getGreenInput());
		  centerPixelGAverageMod = TheModifierFactory.createAverage(centerGAverageInput, true);
		  // set to be a running average
		 // centerPixelGAverageMod.setRun(true);
		
		  // upper Left pixel RGB summation setup
		  ArrayList<Input> upperLeftSumInput = new ArrayList<Input>(3);
		  upperLeftSumInput.add(upperLeftPixel.getRedInput());
		  upperLeftSumInput.add(upperLeftPixel.getGreenInput());
		  upperLeftSumInput.add(upperLeftPixel.getBlueInput());
		  upperLeftPixelSumMod = TheModifierFactory.createSum(upperLeftSumInput, true);
		  
		  // lower Left pixel RGB summation setup
		  ArrayList<Input> lowerLeftSumInput = new ArrayList<Input>(3);
		  lowerLeftSumInput.add(lowerLeftPixel.getRedInput());
		  lowerLeftSumInput.add(lowerLeftPixel.getGreenInput());
		  lowerLeftSumInput.add(lowerLeftPixel.getBlueInput());
		  lowerLeftPixelSumMod = TheModifierFactory.createSum(lowerLeftSumInput, true);
		  
		  // upper Right pixel RGB summation setup
		  ArrayList<Input> upperRightSumInput = new ArrayList<Input>(3);
		  upperRightSumInput.add(upperRightPixel.getRedInput());
		  upperRightSumInput.add(upperRightPixel.getGreenInput());
		  upperRightSumInput.add(upperRightPixel.getBlueInput());
		  upperRightPixelSumMod = TheModifierFactory.createSum(upperRightSumInput, true);
		  
		  // lower Right pixel RGB summation setup
		  ArrayList<Input> lowerRightSumInput = new ArrayList<Input>(3);
		  lowerRightSumInput.add(lowerRightPixel.getRedInput());
		  lowerRightSumInput.add(lowerRightPixel.getGreenInput());
		  lowerRightSumInput.add(lowerRightPixel.getBlueInput());
		  lowerRightPixelSumMod = TheModifierFactory.createSum(lowerRightSumInput, true);
		  
		  
		  // 4 outer pixel RGB average setup
		  ArrayList<Input> outerFourPixelsAverageInput = new ArrayList<Input>(4);
		  outerFourPixelsAverageInput.add(upperLeftPixelSumMod);
		  outerFourPixelsAverageInput.add(lowerLeftPixelSumMod);
		  outerFourPixelsAverageInput.add(upperRightPixelSumMod);
		  outerFourPixelsAverageInput.add(lowerRightPixelSumMod);
		  outerFourPixelsAverageMod = TheModifierFactory.createAverage(outerFourPixelsAverageInput, true);
		  
		  // highpass of 4 pixels average for controlling the harmony instrument 
		  ArrayList<Input> outerFourPixelsAverageHighPassInput = new ArrayList<Input>(2);
		  outerFourPixelsAverageHighPassInput.add(TheInputFactory.createConstant(150, false));
		  outerFourPixelsAverageHighPassInput.add(outerFourPixelsAverageMod);
		  outerFourPixelsAverageHighPassMod = TheModifierFactory.createHighPass(outerFourPixelsAverageHighPassInput, true);
		  
			// ********************
			// Output Adapter Setup
			// ********************
		  
		  outerFourPixelsAverageHighPassScaleAdapter = TheOutputAdapterFactory.createScaleAdapter(OutputRanges.Pitch, outerFourPixelsAverageHighPassMod);
		  
		  centerPixelAverageScaleAdapter = TheOutputAdapterFactory.createScaleAdapter(OutputRanges.Pitch, centerPixelGAverageMod);
		  
		  lowerLeftPixelAverageScaleAdapter = TheOutputAdapterFactory.createScaleAdapter(OutputRanges.Pitch, lowerLeftPixelRAverageMod);
		  
		  upperRightPixelAverageScaleAdapter = TheOutputAdapterFactory.createScaleAdapter(OutputRanges.Velocity, upperLeftPixelSumMod);
		  
		  // ********************	
		  // midi output setup
		  // ********************
		  
		  midiYoke1Rec = TheMidiManager.getMidiYoke1Receiver();
		  
		  dronePitchVelOut = TheMidiOutParameterFactory.createPitchVelocityMidiOutParameter
		  												(lowerLeftPixelAverageScaleAdapter, TheInputFactory.createConstant(64, false), midiYoke1Rec, MidiVoices.Drone.ChannelNumber);
		  
		  harmPitchVelOut = TheMidiOutParameterFactory.createPitchVelocityMidiOutParameter
		  												(outerFourPixelsAverageHighPassScaleAdapter, upperRightPixelAverageScaleAdapter, midiYoke1Rec, MidiVoices.Harmony.ChannelNumber);
		  
		  arpPitchVelOut = TheMidiOutParameterFactory.createPitchVelocityMidiOutParameter
		  												(centerPixelAverageScaleAdapter, TheInputFactory.createConstant(64, false), midiYoke1Rec, MidiVoices.Arpeggio.ChannelNumber);
		  
		  
		  
	}
	
	
	public void Draw() {
		// Since everything is handled by the factories and Update Manager, we don't have to do anything here to get sound out. :D
		// But for debugging purposes, we'll print the values, and circle the middle pixel.
		
		
		fill(0, 0);
		fill (255, 255);
		
		// Draw each color and value to the applet
		//text("R = " + middlePixel.getRedInput().getValue(), 5, 30);

	}

	
	
	public int getFrameRate() {
		return 30;
	}

	public int getHeight() {
		return 480;
	}
	
	public int getWidth() {
		return 640;
	}

}
